package net.oschina.app.protocol;

import android.text.TextUtils;
import android.util.Log;

import net.oschina.app.base.Global;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by Administrator on 2016/12/8 0008.
 * 网络访问的封装类，基类
 * 所有功能片段(首页、应用、游戏片段)访问网络的基类
 */

public abstract class BaseProtocol<T> {
    /**获取数据的流程，实现步骤
     * 1. 优先从本地缓存取数据，假如数据不存在，或者数据失效（数据由时效性，假如失效，返回null），则访问网络
     * 2. 从网络获取最新的数据，假如获取到的数据不为空，则保存数据到本地缓存
     * 3. 解析获取到的数据（来自缓存或者网络） ，比如xml、json数据 解析成 java bean
     * 4. 返回解析后的javabean数据
     */
   //1. 取得数据   onSubLoadData（）
    public T getData(int index){
        String result=null;
        //1.1 从本地缓存取数据
        String cacheData=getDataFromLocal(index);
        if(!TextUtils.isEmpty(cacheData)){
            result=cacheData;
        }
        //1.2 从网络获取最新的数据
        else{
            result=getDataFromNet(index);
        }
        //1.3 解析从缓存或者网络中获取的数据
        return paresData(result);

    }

    private String getDataFromNet(int index) {
        //通过Okhttp访问网络
        //2.1  构建一个http 的客户端，浏览器
        OkHttpClient client=new OkHttpClient();
        //http://127.0.0.1:8090/home?index=0&name=image.jpg
        String url= ServerAPI.BASE_URL+getkey()+"?index="+index+getParams();
        //2.2 构建一个请求
        Request request=new Request.Builder().url(url).build();

        //2.3 执行请求
        try {
            Response respone = client.newCall(request).execute();
            //访问网络成功
            if(respone.isSuccessful()){
                Log.d("heima11","getDataFromNet");
                String result=respone.body().string();
                if(!TextUtils.isEmpty(result)){
                    //1. 把最新的数据缓存到本地
                    saveDataToLocal(result,index);
                    //2. 把结果返回给调用者
                    return  result;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return  null;
    }

    private void saveDataToLocal(String result,int index) {
        //1. 设置要存储的文件
        File file=new File(Global.mContext.getCacheDir(),getkey()+index+getParams());
        //2. 开启一个写入的writer
        BufferedWriter writer=null;
        try {
             writer=new BufferedWriter(new FileWriter(file));
            //2.1 第一行写数据的有效时间  ,30分钟之内有效    当前的时间+30分钟
            long invalidTime=System.currentTimeMillis()+30*60*1000;
            writer.write(invalidTime+"\r\n");
            //2.1 从第二行开始写json数据
            writer.write(result);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(writer!=null){
                try {
                    writer.close();
                    writer=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    //从本地缓存取数据
    private String getDataFromLocal(int index) {
//        CommonUtil.getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        //取得要读取的文件名
        File file=new File(Global.mContext.getCacheDir(),getkey()+index+getParams());
        //假如缓存文件存在，则访问文件
        if(file.exists()){
            BufferedReader reader=null;
            try {
                reader=new BufferedReader(new FileReader(file));
                //读第一行，判断该数据是否有效
              long invalidTime=  Long.valueOf(reader.readLine().trim());
                 if(System.currentTimeMillis()<=invalidTime){
                     //有效数据，则读取具体的内容
                     StringBuilder sb=new StringBuilder();
                     String tempLine=null;
                     while ((tempLine=reader.readLine())!=null){
                         sb.append(tempLine);
                     }
                     return  sb.toString();
                 }else{
                     return  null;
                 }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(reader!=null){
                    try {
                        reader.close();
                        reader=null;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            }

        }else{
            return  null;
        }
        return null;
    }
    //取得要传递的参数，由于基类BaseProtocol不能决定子类如何传参，所以抽象出去 ，由子类取完成
    public abstract String getParams();
    //取得要访问的页面，比如首页功能页面，应用页面，游戏页面 ，在基类中不能决定子类的页面，所以抽象出去
    public abstract String getkey() ;

    //解析数据 ,由于每个子类请求的数据都有差异，所以解析数据的方法应该抽象出去，由子类来实现
    public abstract T paresData(String result) ;
}
